package cn.fcj.f20240328.fsocket.chanelhandler;

import cn.fcj.f20240328.fsocket.ReadDataEntity;
import cn.fcj.f20240328.fsocket.base.FBaseNIOSocket;
import cn.fcj.f20240328.fsocket.base.ISocketEventHandler;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;

/**
 * @项目名称:FSocket
 * @功能描述:实现事件处理接口,消息为head+内容，head中放内容长度
 * @开发　者:mochhk
 * @邮　　箱:mochhk@163.com
 * @CreateDate:2024/4/5 13:31
 */
public class DEFMsgLengthHandlerImp implements ISocketEventHandler {
    @Override
    public ByteBuffer sendData(SelectionKey key, byte[] msg) throws IOException {
        int head = msg.length;
        ByteBuffer byteBuffer = ByteBuffer.allocate(4 + head);
        byteBuffer.put(ReadDataEntity.intToBytes(head));
        byteBuffer.put(msg);
        return byteBuffer;
    }

    @Override
    public void receiveDataForChannel(SelectionKey key) throws IOException {
        SocketChannel channel = (SocketChannel) key.channel();
        System.out.println("channelReadable===ChannelLengthHandlerImp====================开始=====");
        readForAllocationData(channel);
    }

    @Override
    public void exceptionHandler(Exception e, FBaseNIOSocket.ErrorCode errorCode, SelectionKey key) {

    }

    @Override
    public void onConnected(SelectionKey key) throws IOException {

    }

    /**
     * 以消息内容的长度设置缓冲区的大小，一次读取一个完整的消息
     * @param channel
     * @throws IOException
     */
    public void readForAllocationData(SocketChannel channel) throws IOException{
        ByteBuffer bodyBuffer=ByteBuffer.allocate(ReadDataEntity.BUFFER_LENGTH);
        int len=-1;
        ReadDataEntity readDataEntity=new ReadDataEntity();
        readHeadBodyLength(channel,readDataEntity);
        if(readDataEntity.bodyLen>0){
            bodyBuffer=ByteBuffer.allocate(readDataEntity.bodyLen);
        }
        len=ReadDataEntity.readBuffer(channel,bodyBuffer);
//        System.out.println("channelReadable===ChannelLengthHandlerImp===11===bodyLen=:"+bodyLen+"===currLen=:"+currLen+"===bodyBuffer=limt=:"+bodyBuffer.limit());
        if(readDataEntity.bodyLen==len){
            bodyBuffer.flip();
            bodyBuffer.get(readDataEntity.byteBody);
            System.out.println("channelReadable=="+channel.getRemoteAddress().toString()+"===finished===:" + readDataEntity.bodyToString());
            readDataEntity.bodyLen=-1;
            readDataEntity.currLen=0;
            bodyBuffer.clear();
        }
    }
    /**
     * 固定缓存区大小，按消息头中的内容长度，连续读取消息，直到读取到完整的消息。
     * @param channel
     * @throws IOException
     */
    public void readData(SocketChannel channel) throws IOException{
        ByteBuffer bodyBuffer=ByteBuffer.allocate(ReadDataEntity.BUFFER_LENGTH);
        ReadDataEntity readDataEntity=new ReadDataEntity();
        readHeadBodyLength(channel,readDataEntity);
        //读取头中的body长度
        if(readDataEntity.bodyLen>0){
            readDataEntity.byteBody=new byte[readDataEntity.bodyLen];
        }
        int len=-1;
        while (readDataEntity.currLen<readDataEntity.bodyLen){
            //剩于长度大于缓冲区的大小，全部读出放入body
            if(readDataEntity.bodyLen-readDataEntity.currLen>ReadDataEntity.BUFFER_LENGTH)
            {
                len=ReadDataEntity.readBuffer(channel,bodyBuffer);
                bodyBuffer.flip();
                readDataEntity.addByteToByteBody(bodyBuffer.array());
//                System.arraycopy(bodyBuffer.array(), 0, readDataEntity.byteBody, readDataEntity.currLen, bodyBuffer.limit());
                bodyBuffer.clear();
                readDataEntity.currLen+=len;
            }
            else{
                //剩于长度小于缓冲区的大小，则按剩余的数据长度读出放入body
                ByteBuffer readBuffer=ByteBuffer.allocate(readDataEntity.bodyLen-readDataEntity.currLen);
                len=ReadDataEntity.readBuffer(channel,readBuffer);
                readBuffer.flip();
                readDataEntity.addByteToByteBody(readBuffer.array());
//                System.arraycopy(readBuffer.array(), 0, readDataEntity.byteBody, readDataEntity.currLen, readBuffer.limit());
                readBuffer.clear();
                readDataEntity.currLen+=len;
                System.out.println("channelReadable=="+channel.getRemoteAddress().toString()+"=1==finished===:" + readDataEntity.bodyToString());
                System.out.println("channelReadable===readData=1=====bodyLen=:"+readDataEntity.bodyLen+"==currLen=:"+readDataEntity.currLen);
                readDataEntity.byteBody=null;
                readDataEntity.bodyLen=-1;
                //接着读取下一个数据包的头信息
                readHeadBodyLength(channel,readDataEntity);
                if(readDataEntity.bodyLen>0){
                    readDataEntity.byteBody=new byte[readDataEntity.bodyLen];
                }

            }
        }
        readDataEntity.currLen=0;
    }

    /**
     * 从数据中读取消息头部信息，获取消息内容长度
     * @param channel
     * @param readDataEntity
     * @return
     * @throws IOException
     */
    public int readHeadBodyLength(SocketChannel channel,ReadDataEntity readDataEntity)throws IOException{
        ByteBuffer headBuffer=ByteBuffer.allocate(ReadDataEntity.HEAD_LENGTH);
        if(readDataEntity.bodyLen<0){
            int len=ReadDataEntity.readBuffer(channel,headBuffer);
            System.out.println("channelReadable===readHeadBodyLength===headBuffer===len=:"+len);
            headBuffer.flip();
            if(headBuffer.limit()==ReadDataEntity.HEAD_LENGTH){
                readDataEntity.bodyLen=ReadDataEntity.byteArrayToInt(headBuffer.array());
                headBuffer.clear();
            }
            if(readDataEntity.bodyLen<=0){
                readDataEntity.bodyLen=-1;
            }
            System.out.println("channelReadable===readHeadBodyLength======bodyLen=:"+readDataEntity.bodyLen);
        }
        return readDataEntity.bodyLen;
    }
}
